package com.meryl.dtk;

import com.intellij.ide.IdeView;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.impl.file.PsiDirectoryFactory;
import com.meryl.dtk.dialog.ServiceDlg;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class CreateServiceAction extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        Project project = e.getProject();

        IdeView ideView = e.getRequiredData(LangDataKeys.IDE_VIEW);
        PsiDirectory directory = ideView.getOrChooseDirectory();
        VirtualFile dirPath = directory.getVirtualFile();
        String path = dirPath.getPath();

        String packageName = path.substring(path.indexOf("java") + 5).replace("/", ".");

        String defaultBaseClassName = "com.jds.core.service.impl.BaseServiceImpl";

        String key = "JdsServiceBaseClass";
        String jdsBaseClassStore = PropertiesComponent.getInstance().getValue(key);

        ServiceDlg serviceDlg = new ServiceDlg();
        if (serviceDlg.getTxtBaseClass() != null) {
            serviceDlg.getTxtBaseClass().setText(defaultBaseClassName);
            if (jdsBaseClassStore != null && !jdsBaseClassStore.isBlank() && !jdsBaseClassStore.isEmpty()) {
                serviceDlg.getTxtBaseClass().setText(jdsBaseClassStore);
            } else {
                serviceDlg.getTxtBaseClass().setText(defaultBaseClassName);
            }
        }

        DialogBuilder dialogBuilder = new DialogBuilder(project);
        dialogBuilder.setCenterPanel(serviceDlg.getRootPanel());
        dialogBuilder.setTitle("Create Service");
        dialogBuilder.show();

        if (dialogBuilder.getDialogWrapper().getExitCode() == DialogWrapper.CANCEL_EXIT_CODE) {
            return;
        }

        String baseClassName = serviceDlg.getTxtBaseClass().getText();
        if (baseClassName == null || baseClassName.isEmpty() || baseClassName.isBlank()) {
            baseClassName = defaultBaseClassName;
        }
        String baseClassShortName = baseClassName.substring(baseClassName.lastIndexOf(".") + 1);

        if (!baseClassName.equals(defaultBaseClassName)) {
            PropertiesComponent.getInstance().setValue(key, baseClassName);
        } else {
            PropertiesComponent.getInstance().setValue(key, null);
        }

        String serviceName = serviceDlg.getTxtServiceName().getText();
        if (serviceName == null || serviceName.isEmpty() || serviceName.isBlank()) {
            Messages.showErrorDialog(new String("Please input service name".getBytes(), StandardCharsets.UTF_8), "Error");
            return;
        }

        if (!packageName.contains("module")) {
            Messages.showErrorDialog("The Jds module is not included in the project. Please create the Jds module first", "Error");
            return;
        }

        String interfaceText = "package " + packageName + ";\n" +
                "\n" +
                "public interface " + serviceName + "Service {\n" +
                "}\n";

        String classText = "package " + packageName + ".impl;\n" +
                "\n" +
                "import " + baseClassName + ";\n" +
                "import " + packageName + "." + serviceName + "Service;\n" +
                "import org.springframework.stereotype.Service;\n" +
                "\n" +
                "@Service\n" +
                "public class " + serviceName + "ServiceImpl extends " + baseClassShortName + " implements " + serviceName + "Service {\n" +
                "}\n";

        WriteCommandAction.runWriteCommandAction(project, () -> {
            try {
                PsiDirectoryFactory.getInstance(project)
                        .createDirectory(dirPath)
                        .createFile(serviceName + "Service.java")
                        .getVirtualFile()
                        .setBinaryContent(interfaceText.getBytes(StandardCharsets.UTF_8));

                VirtualFile implDir = dirPath.findChild("impl");
                if (implDir == null || !implDir.exists()) {
                    implDir = dirPath.createChildDirectory(this, "impl");
                }
                PsiDirectoryFactory.getInstance(project)
                        .createDirectory(implDir)
                        .createFile(serviceName + "ServiceImpl.java")
                        .getVirtualFile()
                        .setBinaryContent(classText.getBytes(StandardCharsets.UTF_8));
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        });
    }
}
